home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
gfx
/
jpegaga2.lha
/
jpegAGAsrc
/
ppm2aga
/
ppmlib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-25
|
15KB
|
604 lines
/* pbm utility library
**
** Copyright (C) 1988 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
/* modified by Günther Röhrich */
/* WARNING: This file is not for use with normal pbm programs */
/* support functions for the ppm stuff */
#include <stdarg.h>
#include "ppm.h"
#include "ppm2AGA.h"
#include "libpbm.h"
#include "libppm.h"
#include "libpgm.h"
extern jmp_buf ErrorEnv;
static bit pbm_getbit(FILE *);
extern pixel **pixels;
extern int cols;
extern int rows;
extern int rowcnt;
extern pixel *pixrow;
extern pixval maxval;
extern int ppmformat;
extern int ColorRegMax;
extern long *thisrerr;
extern long *nextrerr;
extern long *thisgerr;
extern long *nextgerr;
extern long *thisberr;
extern long *nextberr;
extern int Convert4096;
extern int Convert262144;
extern int fs_direction;
#define FS_SCALE 1024
void FSrow(pixel *pixelrow, int cols);
/* this is called when an error in ppm2ilbm() is found */
void pm_error(char *format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args); /* modify this if we don't output to stdout any more */
va_end(args);
longjmp(ErrorEnv, 10);
}
/* this is defined in ppm2AGA.c
void pm_message(char *format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
*/
void ppm_readppminitrest(FILE *file, int *colsP, int *rowsP, pixval *maxvalP)
{
int maxval;
/* Read size. */
*colsP = pbm_getint( file );
*rowsP = pbm_getint( file );
/* Read maxval. */
maxval = pbm_getint( file );
if ( maxval > PPM_MAXMAXVAL )
pm_error(
"maxval is too large - try reconfiguring with PGM_BIGGRAYS\n\
or without PPM_PACKCOLORS\n" );
*maxvalP = maxval;
}
pixval ppm_pbmmaxval = 1;
void ppm_readppminit(FILE *file, int *colsP, int *rowsP,
pixval *maxvalP, int *formatP)
{
/* Check magic number. */
*formatP = pbm_readmagicnumber( file );
switch ( PPM_FORMAT_TYPE(*formatP) )
{
case PPM_TYPE:
ppm_readppminitrest( file, colsP, rowsP, maxvalP );
break;
case PGM_TYPE:
pgm_readpgminitrest( file, colsP, rowsP, maxvalP );
break;
case PBM_TYPE:
pbm_readpbminitrest( file, colsP, rowsP );
*maxvalP = ppm_pbmmaxval;
break;
default:
pm_error( "bad magic number - not a ppm, pgm, or pbm file\n" );
}
}
char pbm_getc(FILE *file)
{
register int ich;
register char ch;
ich = getc( file );
if ( ich == EOF )
pm_error( "EOF / read error\n" );
ch = (char) ich;
if ( ch == '#' )
{
do
{
ich = getc( file );
if ( ich == EOF )
pm_error( "EOF / read error\n" );
ch = (char) ich;
}
while ( ch != '\n' && ch != '\r' );
}
return ch;
}
unsigned char pbm_getrawbyte(FILE *file)
{
register int iby;
iby = getc( file );
if ( iby == EOF )
pm_error( "EOF / read error\n" );
return (unsigned char) iby;
}
int pbm_getint(FILE *file)
{
register char ch;
register int i;
do
{
ch = pbm_getc( file );
}
while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );
if ( ch < '0' || ch > '9' )
pm_error( "junk in file where an integer should be\n" );
i = 0;
do
{
i = i * 10 + ch - '0';
ch = pbm_getc( file );
}
while ( ch >= '0' && ch <= '9' );
return i;
}
int pbm_readmagicnumber(FILE *file)
{
int ich1, ich2;
ich1 = getc( file );
if ( ich1 == EOF )
pm_error( "EOF / read error reading magic number\n" );
ich2 = getc( file );
if ( ich2 == EOF )
pm_error( "EOF / read error reading magic number\n" );
return ich1 * 256 + ich2;
}
void pbm_readpbminitrest(FILE *file, int *colsP, int *rowsP )
{
/* Read size. */
*colsP = pbm_getint( file );
*rowsP = pbm_getint( file );
}
void pgm_readpgminitrest(FILE *file, int *colsP, int *rowsP, gray *maxvalP)
{
int maxval;
/* Read size. */
*colsP = pbm_getint( file );
*rowsP = pbm_getint( file );
/* Read maxval. */
maxval = pbm_getint( file );
if ( maxval > PGM_MAXMAXVAL )
pm_error( "maxval is too large - try reconfiguring with PGM_BIGGRAYS\n" );
*maxvalP = maxval;
}
/* Variable-sized arrays. */
char*
pm_allocrow( cols, size )
int cols;
int size;
{
register char* itrow;
itrow = (char*) malloc( cols * size );
if ( itrow == (char*) 0 )
pm_error( "out of memory allocating a row\n" );
return itrow;
}
void
pm_freerow( itrow )
char* itrow;
{
free( itrow );
}
char**
pm_allocarray( cols, rows, size )
int cols, rows;
int size;
{
char** its;
int i;
its = (char**) malloc( (rows + 1) * sizeof(char*) );
if ( its == (char**) 0 )
pm_error( "out of memory allocating an array\n" );
/* initialize the array, modified by Günther Röhrich */
/* this is needed for using pm_freearray() even if the array */
/* is not completely allocated */
memset((void *)its, 0, (rows + 1) * sizeof(char*));
its[rows] = its[0] = (char*) malloc( rows * cols * size );
if ( its[0] != (char*) 0 )
for ( i = 1; i < rows; ++i )
its[i] = &(its[0][i * cols * size]);
else
for( i = 0; i < rows; ++i )
{
/* modified by Günther Röhrich */
if(!(its[i] = (char*) malloc( cols * size )))
{
pm_freearray(its, rows);
its = NULL;
break;
}
}
return its;
}
void
pm_freearray( its, rows )
char** its;
int rows;
{
int i;
if( its[rows] != (char*) 0 )
free( its[rows] );
else
for( i = 0; i < rows; ++i )
pm_freerow( its[i] );
free( its );
}
void ppm_readppmrow(FILE* file, pixel* pixelrow, int cols, pixval maxval, int format)
{
register int col;
register pixel* pP;
register pixval r, g, b;
gray* grayrow;
register gray* gP;
bit* bitrow;
register bit* bP;
switch ( format )
{
case PPM_FORMAT:
for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
{
r = pbm_getint( file );
#ifdef DEBUG
if ( r > maxval )
pm_error( "r value out of bounds (%u > %u)\n", r, maxval );
#endif /*DEBUG*/
g = pbm_getint( file );
#ifdef DEBUG
if ( g > maxval )
pm_error( "g value out of bounds (%u > %u)\n", g, maxval );
#endif /*DEBUG*/
b = pbm_getint( file );
#ifdef DEBUG
if ( b > maxval )
pm_error( "b value out of bounds (%u > %u)\n", b, maxval );
#endif /*DEBUG*/
PPM_ASSIGN( *pP, r, g, b );
}
if(Convert4096 || Convert262144) FSrow(pixelrow, cols);
break;
case RPPM_FORMAT:
for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
{
r = pbm_getrawbyte( file );
#ifdef DEBUG
if ( r > maxval )
pm_error( "r value out of bounds (%u > %u)\n", r, maxval );
#endif /*DEBUG*/
g = pbm_getrawbyte( file );
#ifdef DEBUG
if ( g > maxval )
pm_error( "g value out of bounds (%u > %u)\n", g, maxval );
#endif /*DEBUG*/
b = pbm_getrawbyte( file );
#ifdef DEBUG
if ( b > maxval )
pm_error( "b value out of bounds (%u > %u)\n", b, maxval );
#endif /*DEBUG*/
PPM_ASSIGN( *pP, r, g, b );
}
if(Convert4096 || Convert262144) FSrow(pixelrow, cols);
break;
case PGM_FORMAT:
case RPGM_FORMAT:
grayrow = pgm_allocrow( cols );
pgm_readpgmrow( file, grayrow, cols, maxval, format );
for ( col = 0, gP = grayrow, pP = pixelrow; col < cols; ++col, ++gP, ++pP )
{
r = *gP;
PPM_ASSIGN( *pP, r, r, r );
}
pgm_freerow( grayrow );
break;
case PBM_FORMAT:
case RPBM_FORMAT:
bitrow = pbm_allocrow( cols );
pbm_readpbmrow( file, bitrow, cols, format );
for ( col = 0, bP = bitrow, pP = pixelrow; col < cols; ++col, ++bP, ++pP )
{
r = ( *bP == PBM_WHITE ) ? maxval : 0;
PPM_ASSIGN( *pP, r, r, r );
}
pbm_freerow( bitrow );
break;
default:
pm_error( "can't happen\n" );
}
}
/* converts one row from 16M colors to 4096/262144 colors using FS dithering */
void FSrow(pixel *pixelrow, int cols)
{
/* if floyd is nonzero we will use Floyd-Steinberg dithering */
register int col, limitcol;
register long sg, sr, sb, err;
long *temperr;
register pixel *pP;
for ( col = 0; col < cols + 2; ++col )
nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
if ( fs_direction )
{
col = 0;
limitcol = cols;
/* pP = pixels[row]; */
pP = pixelrow;
}
else
{
col = cols - 1;
limitcol = -1;
/* pP = &(pixels[row][col]); */
pP = &pixelrow[col];
}
do
{
/* Use Floyd-Steinberg errors to adjust actual color. */
sr = PPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
sg = PPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
sb = PPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
if ( sr < 0 ) sr = 0;
else if ( sr > maxval ) sr = maxval;
if ( sg < 0 ) sg = 0;
else if ( sg > maxval ) sg = maxval;
if ( sb < 0 ) sb = 0;
else if ( sb > maxval ) sb = maxval;
/* PPM_ASSIGN( *pP, sr, sg, sb ); */
if(Convert4096)
PPM_ASSIGN(*pP, sr&0xF0, sg&0xF0, sb&0xF0);
else
PPM_ASSIGN(*pP, sr&0xFC, sg&0xFC, sb&0xFC);
/* Propagate Floyd-Steinberg error terms. */
if ( fs_direction )
{
err = ( sr - (long) PPM_GETR(*pP) ) * FS_SCALE;
thisrerr[col + 2] += ( err * 7 ) / 16;
nextrerr[col ] += ( err * 3 ) / 16;
nextrerr[col + 1] += ( err * 5 ) / 16;
nextrerr[col + 2] += ( err ) / 16;
err = ( sg - (long) PPM_GETG(*pP) ) * FS_SCALE;
thisgerr[col + 2] += ( err * 7 ) / 16;
nextgerr[col ] += ( err * 3 ) / 16;
nextgerr[col + 1] += ( err * 5 ) / 16;
nextgerr[col + 2] += ( err ) / 16;
err = ( sb - (long) PPM_GETB(*pP) ) * FS_SCALE;
thisberr[col + 2] += ( err * 7 ) / 16;
nextberr[col ] += ( err * 3 ) / 16;
nextberr[col + 1] += ( err * 5 ) / 16;
nextberr[col + 2] += ( err ) / 16;
}
else
{
err = ( sr - (long) PPM_GETR(*pP) ) * FS_SCALE;
thisrerr[col ] += ( err * 7 ) / 16;
nextrerr[col + 2] += ( err * 3 ) / 16;
nextrerr[col + 1] += ( err * 5 ) / 16;
nextrerr[col ] += ( err ) / 16;
err = ( sg - (long) PPM_GETG(*pP) ) * FS_SCALE;
thisgerr[col ] += ( err * 7 ) / 16;
nextgerr[col + 2] += ( err * 3 ) / 16;
nextgerr[col + 1] += ( err * 5 ) / 16;
nextgerr[col ] += ( err ) / 16;
err = ( sb - (long) PPM_GETB(*pP) ) * FS_SCALE;
thisberr[col ] += ( err * 7 ) / 16;
nextberr[col + 2] += ( err * 3 ) / 16;
nextberr[col + 1] += ( err * 5 ) / 16;
nextberr[col ] += ( err ) / 16;
}
if ( fs_direction )
{
++col;
++pP;
}
else
{
--col;
--pP;
}
} while ( col != limitcol );
temperr = thisrerr;
thisrerr = nextrerr;
nextrerr = temperr;
temperr = thisgerr;
thisgerr = nextgerr;
nextgerr = temperr;
temperr = thisberr;
thisberr = nextberr;
nextberr = temperr;
fs_direction = ! fs_direction;
}
void pgm_readpgmrow(FILE* file, gray* grayrow, int cols, gray maxval, int format)
{
register int col;
register gray* gP;
bit* bitrow;
register bit* bP;
switch ( format )
{
case PGM_FORMAT:
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
*gP = pbm_getint( file );
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)\n", *gP, maxval );
#endif /*DEBUG*/
}
break;
case RPGM_FORMAT:
for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
{
*gP = pbm_getrawbyte( file );
#ifdef DEBUG
if ( *gP > maxval )
pm_error( "value out of bounds (%u > %u)\n", *gP, maxval );
#endif /*DEBUG*/
}
break;
case PBM_FORMAT:
case RPBM_FORMAT:
bitrow = pbm_allocrow( cols );
pbm_readpbmrow( file, bitrow, cols, format );
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
*gP = ( *bP == PBM_WHITE ) ? maxval : 0;
pbm_freerow( bitrow );
break;
default:
pm_error( "can't happen\n" );
}
}
void pbm_readpbmrow(FILE *file, bit *bitrow, int cols, int format )
{
register int col, bitshift;
register unsigned char item;
register bit* bP;
switch ( format )
{
case PBM_FORMAT:
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
*bP = pbm_getbit( file );
break;
case RPBM_FORMAT:
bitshift = -1;
for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
{
if ( bitshift == -1 )
{
item = pbm_getrawbyte( file );
bitshift = 7;
}
*bP = ( item >> bitshift ) & 1;
--bitshift;
}
break;
default:
pm_error( "can't happen\n" );
}
}
static bit pbm_getbit(FILE *file )
{
register char ch;
do
{
ch = pbm_getc( file );
}
while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );
if ( ch != '0' && ch != '1' )
pm_error( "junk in file where bits should be\n" );
return ( ch == '1' ) ? 1 : 0;
}
pixel *next_pixrow(FILE *fp, int row, int ColorShift)
{
int i;
pixel *pP;
if( pixels )
pixrow = pixels[row];
else {
if( row != rowcnt )
pm_error("big mistake\n");
rowcnt++;
ppm_readppmrow(fp, pixrow, cols, maxval, ppmformat);
if(maxval == 255)
{
for(i=0,pP=pixrow; i<cols; i++,pP++)
{
pP->r = pP->r >> ColorShift;
pP->g = pP->g >> ColorShift;
pP->b = pP->b >> ColorShift;
}
}
else
{
for(i=0,pP=pixrow; i<cols; i++,pP++) PPM_DEPTH(*pP, *pP, maxval, ColorRegMax);
}
}
return pixrow;
}